package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.ui.Mouse;
	
	import com.atomos.log.AtomosDebug;
	import com.atomos.particle.Particle;
	import com.atomos.particle.ParticleManager;
	import com.atomos.strategy.action.StackAction;
	import com.atomos.strategy.action.position.MoveAction;
	import com.atomos.strategy.action.velocity.FrictionAction;
	import com.atomos.strategy.action.velocity.PonctualForceAction;
	import com.atomos.strategy.emission.FixedCountEmission;
	import com.atomos.strategy.initialize.StackInitializer;
	import com.atomos.strategy.initialize.life.LifeInitializer;
	import com.atomos.strategy.initialize.position.BoxInitializer;
	import com.atomos.strategy.initialize.velocity.ExplosionInitializer;
	import com.atomos.system.SimpleParticleSystem;
	import com.atomos.utils.AtomosMonitorFieldsList;
	import com.bourre.collection.Iterator;
	import com.bourre.log.Logger;
	import com.bourre.utils.FlashInspectorLayout;
	import com.kairos.engine.RTBeacon;
	import com.kairos.utils.Monitor;
	import com.kairos.utils.MonitorFieldsList;	

	[SWF(width="550",height="400",frameRate="40",backgroundColor="#000000")]
	public class AttractionExample extends Sprite
	{
		// The particle system use by that example
		protected var _system : SimpleParticleSystem;
		// The PonctualForceAction object used to perform the attraction
		protected var _attraction : PonctualForceAction;
		
		public function AttractionExample ()
		{
			Logger.getInstance().addLogListener( FlashInspectorLayout.getInstance(), AtomosDebug.CHANNEL );
			
			// Set the maximum step for the current animation
			RTBeacon.getInstance().setMaxStepSize( 100 );
			
			// Creating a monitor 
			var monitor : Monitor = new Monitor( 140, 60 );
			monitor.addField( MonitorFieldsList.FPS );
			monitor.addField( MonitorFieldsList.MEMORY );
			monitor.addField( AtomosMonitorFieldsList.PARTICLES );
			monitor.start();
			addChild ( monitor );
			
			// Creating the stack for particles action
			var action : StackAction = new StackAction();
			
			// We store that strategy in order to make it move according to the mouse.
			_attraction = new PonctualForceAction( new Point(), 120, -100 );
			action.add( _attraction );
			
			action.add( new FrictionAction ( .995 ) );
			action.add( new MoveAction() );
			
			/* The strategy below is a custom strategy specifically 
			 * created for that example, you can find it at the end
			 * of this file. It simply make particles bouncing on the
			 * edges of the screen.
			 */
			action.add( new WorldBounceAction ( 550, 400 ) );
			
			// Creating the stack for particles initialization
			var initializer : StackInitializer = new StackInitializer();
			initializer.add( new LifeInitializer ( 1 ) );
			initializer.add( new BoxInitializer ( new Rectangle( 0, 0, 550, 400 ) ) );
			initializer.add( new ExplosionInitializer ( 50, null, 100 ) );
			
			// Creating the emitter with stacks and launch the emission
			var emission : FixedCountEmission = new FixedCountEmission ( Particle, new Point(), 200 );
			_system = new SimpleParticleSystem( initializer, action );
			_system.emit( emission ); 
			// Adding the draw routine
			addEventListener( Event.ENTER_FRAME, enterFrameHandler );
			stage.addEventListener( MouseEvent.MOUSE_MOVE, mouseMoveHandler );
			
			Mouse.hide();
		}
		
		public function mouseMoveHandler ( e : MouseEvent ) : void
		{
			_attraction.setForcePosition( new Point( e.stageX, e.stageY ) );
			
		}
		
		public function enterFrameHandler ( e : Event ) : void
		{
			// Clear the scene
			graphics.clear();
			graphics.lineStyle( 2, 0xffffff );

			// Get an iterator of all particles of the scene
			var i : Iterator = ParticleManager.getInstance().getParticles().iterator();
			var p : Particle;
					
			// For each particle in the manager we draw a circle	
			while( i.hasNext() )
			{
				p = i.next() as Particle;
				
				graphics.moveTo( p.lastPosition.x, p.lastPosition.y );
				graphics.lineTo( p.position.x+1, p.position.y+1 );
			}
			var pos : Point = _attraction.getForcePosition();
			
			
			graphics.lineStyle( 1, 0xffffff );
			
			graphics.drawCircle( pos.x, pos.y, _attraction.getForceRadius() );
			graphics.moveTo( pos.x, pos.y -4 );
			graphics.lineTo( pos.x, pos.y +4 );
			graphics.moveTo( pos.x -4, pos.y );
			graphics.lineTo( pos.x +4, pos.y );
		}
	}
}

import com.atomos.particle.Particle;
import com.atomos.strategy.action.AbstractAction;

internal class WorldBounceAction extends AbstractAction
{
	public var width : Number;
	public var height : Number;
	
	public function WorldBounceAction ( w : Number, h : Number )
	{
		width = w;
		height = h;
	}
	
	public override function process(particle:Particle):void
	{
		if( particle.position.x < 0 ) 
		{
			particle.position.x = 0;
			particle.velocity.x *= -1;
		}
		else if( particle.position.x > width ) 
		{
			particle.position.x = width;
			particle.velocity.x *= -1;
		}
		
		if( particle.position.y < 0 ) 
		{
			particle.position.y = 0;
			particle.velocity.y *= -1;
		}
		else if( particle.position.y > height ) 
		{
			particle.position.y = height;
			particle.velocity.y *= -1;
		}
	}
}